<template>
  <div class="web-image-preview">
    <!-- 图片网格 -->
    <div class="image-grid" v-if="images && images.length > 0">
      <div 
        v-for="(image, index) in images" 
        :key="image.id || index"
        class="image-item"
        @click="handlePreview(index)"
      >
        <el-image 
          :src="getImageUrl(image)" 
          fit="cover"
          class="image-preview"
          :preview-src-list="imageUrlList"
          :initial-index="index"
          preview-teleported
          @error="handleImageError"
          @load="handleImageLoad"
        />
        <!-- 图片信息 -->
        <div v-if="showImageInfo" class="image-info">
          <span class="image-name">{{ getImageName(image) }}</span>
          <span v-if="getImageSize(image)" class="image-size">{{ formatFileSize(getImageSize(image)) }}</span>
        </div>
      </div>
    </div>
    
    <!-- 空状态 -->
    <div v-else class="empty-state">
      <el-icon :size="48" color="#ccc">
        <Picture />
      </el-icon>
      <span class="empty-text">{{ emptyText }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
/**
 * Web端图片预览组件
 * 生产环境标准实现，支持图片预览、错误处理、加载状态等功能
 * 
 * @author Wu.Liang
 * @date 2025-01-30
 * @version 1.0.0
 */

import { computed } from 'vue'
import { Picture } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'

// Props定义
interface Props {
  // 图片列表
  images: any[]
  // 是否显示图片信息
  showImageInfo?: boolean
  // 空状态文本
  emptyText?: string
  // 图片URL字段名
  urlField?: string
  // 图片名称字段名
  nameField?: string
  // 图片大小字段名
  sizeField?: string
}

const props = withDefaults(defineProps<Props>(), {
  images: () => [],
  showImageInfo: false,
  emptyText: '暂无图片',
  urlField: 'fileUrl',
  nameField: 'fileName',
  sizeField: 'fileSize'
})

// Emits定义
const emit = defineEmits<{
  preview: [data: { index: number; image: any; url: string }]
  error: [data: { index?: number; image?: any; error: any }]
  load: [data: { event: any }]
}>()

// 计算属性：有效的图片列表
const validImages = computed(() => {
  if (!props.images || !Array.isArray(props.images)) {
    return []
  }
  
  return props.images.filter(image => {
    const url = getImageUrl(image)
    return url && url.trim() !== ''
  })
})

// 计算属性：图片URL列表（用于预览）
const imageUrlList = computed(() => {
  return validImages.value.map(image => getImageUrl(image))
})

// 获取图片URL
const getImageUrl = (image: any): string => {
  if (!image) return ''
  
  // 支持多种URL字段名
  const url = image[props.urlField] || image.url || image.src || image.fileUrl || ''
  
  // 确保URL是字符串
  return String(url).trim()
}

// 获取图片名称
const getImageName = (image: any): string => {
  if (!image) return ''
  
  const name = image[props.nameField] || image.fileName || image.name || ''
  return String(name).trim() || '未命名图片'
}

// 获取图片大小
const getImageSize = (image: any): number => {
  if (!image) return 0
  
  const size = image[props.sizeField] || image.fileSize || image.size || 0
  return parseInt(size) || 0
}

// 格式化文件大小
const formatFileSize = (fileSize: number): string => {
  if (!fileSize || fileSize === 0) {
    return '0 B'
  }
  
  const units = ['B', 'KB', 'MB', 'GB']
  let size = fileSize
  let unitIndex = 0
  
  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024
    unitIndex++
  }
  
  return `${size.toFixed(1)} ${units[unitIndex]}`
}

// 处理图片预览
const handlePreview = (index: number) => {
  try {
    const imageList = validImages.value
    if (!imageList || imageList.length === 0) {
      ElMessage.warning('暂无图片')
      return
    }
    
    const currentImage = imageList[index]
    const currentUrl = getImageUrl(currentImage)
    
    console.log('图片预览，索引:', index)
    emit('preview', { index, image: currentImage, url: currentUrl })
  } catch (error) {
    console.error('图片预览处理失败:', error)
    ElMessage.error('图片预览失败')
    emit('error', { index, error })
  }
}

// 处理图片加载错误
const handleImageError = (error: any) => {
  console.error('图片加载失败:', error)
  emit('error', { error })
}

// 处理图片加载成功
const handleImageLoad = (event: any) => {
  console.log('图片加载成功:', event)
  emit('load', { event })
}
</script>

<style lang="scss" scoped>
.web-image-preview {
  width: 100%;
}

.image-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 12px;
  padding: 16px;
}

.image-item {
  position: relative;
  aspect-ratio: 1;
  border-radius: 8px;
  overflow: hidden;
  background: #f5f5f5;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  
  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }
  
  &:active {
    transform: translateY(0);
  }
}

.image-preview {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-info {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
  padding: 8px;
  
  .image-name {
    display: block;
    font-size: 12px;
    color: #fff;
    margin-bottom: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  
  .image-size {
    display: block;
    font-size: 10px;
    color: rgba(255, 255, 255, 0.8);
  }
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 16px;
  
  .empty-text {
    margin-top: 12px;
    font-size: 14px;
    color: #999;
  }
}

/* 响应式设计 */
@media screen and (max-width: 768px) {
  .image-grid {
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    gap: 8px;
    padding: 12px;
  }
}

@media screen and (min-width: 1200px) {
  .image-grid {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 16px;
    padding: 20px;
  }
}
</style>
